
class eString
{
  static bool isalpha(wchar_t c)
  {
    return isLower(c) || isUpper(c);
  }

  static bool isLower(wchar_t c)
  {
    static const std::wstring mask(L"\x007A\x0109\x011D\x0135\x0125\x015D\x016D");
    if (0x61 <= c && c <= 0x76 && c != 0x71)   // 0061 a ... 0070 p
      return true;                             // 0072 r ... 0076 v
    return mask.find(c) != std::string::npos;  // z,cx,gx,jx,hx,sx,ux
    return false;
  }

  static bool isUpper(wchar_t c)
  {
    static const std::wstring mask(L"\x005A\x0108\x011C\x0134\x0124\x015C\x016C");
    if (0x41 <= c && c <= 0x56 && c != 0x51)   // 0041 A ... 0050 P
      return true;                             // 0052 R ... 0056 V
    return mask.find(c) != std::string::npos;  // Z,CX,GX,JX,HX,SX,UX
  }

  static wchar_t toupper(wchar_t c)
  {
    static const std::wstring mask(L"\x0109\x011D\x0135\x0125\x015D\x016D");
    if ((0x61 <= c && c <= 0x76 && c != 0x71) || c == 0x7A)// a...p, r...v, z
      return c ^ 0x20;
    return c - (mask.find(c) != std::string::npos);  // cx,gx,jx,hx,sx,ux
  }

  static wchar_t tolower(wchar_t c)
  {
    static const std::wstring mask(L"\x0108\x011C\x0134\x0124\x015C\x016C");
    if ((0x41 <= c && c <= 0x56 && c != 0x51) || c == 0x5A)// A...P, R...V, Z
      return c ^ 0x20;
    return c + (mask.find(c) != std::string::npos);  // CX,GX,JX,HX,SX,UX
  }

  static int cmp(wchar_t c1, wchar_t c2, bool caseSens = false)
  {
    static const std::wstring abc(L"\x0041\x0061\x0042\x0062\x0043\x0063\x0108\x0109\x0044\x0064\x0045\x0065\x0046\x0066\x0047\x0067\x011C\x011D\x0048\x0068\x0124\x0125\x0049\x0069\x004A\x006A\x0134\x0135\x004B\x006B\x004C\x006C\x004D\x006D\x004E\x006E\x004F\x006F\x0050\x0070\x0052\x0072\x0053\x0073\x015C\x015D\x0054\x0074\x0055\x0075\x016C\x016D\x0056\x0076\x005A\x007A");
    size_t n1, n2;
    if (std::string::npos == (n1 = abc.find(c1)) ||
        std::string::npos == (n2 = abc.find(c2)))
    {
      n1 = c1;
      n2 = c2;
    }
    else
      if (!caseSens)
      {
        n1 |= 1;
        n2 |= 1;
      }

    if (n1 < n2)
      return -1;
    if (n1 > n2)
      return 1;
    return 0;
  }
};
